import 'package:flutter/material.dart';

import '../../theme/kq_theme_manager.dart';

/// 完全自定义头部的下拉控件
///
/// 主要用于切换公司和业务，可配合[KqSearchableDropdownList]一起使用
/// @author 周卓
class KqHeaderWithDropdown extends StatefulWidget {
  /// 自定义头部
  final Widget header;

  /// 下拉控制器
  final CustomHeaderDropdownController controller;

  /// 自定义下拉控件
  final Widget Function(CustomHeaderDropdownController dropdownController)
      dropdownBuilder;

  /// 头部高度，非必传，不传则按[title]高度来
  final double? headerHeight;

  /// 头部背景颜色
  final Color? headerBgColor;

  /// 下拉内容背景颜色
  final Color? dropDownBgColor;

  /// 头部点击事件
  final Function(CustomHeaderDropdownController dropdownController) onTitleTap;

  const KqHeaderWithDropdown({
    super.key,
    required this.header,
    required this.onTitleTap,
    required this.dropdownBuilder,
    required this.controller,
    this.headerHeight,
    this.headerBgColor,
    this.dropDownBgColor,
  });

  @override
  State<KqHeaderWithDropdown> createState() => _KqHeaderWithDropdownState();
}

class _KqHeaderWithDropdownState extends State<KqHeaderWithDropdown> {
  final GlobalKey _headerKey = GlobalKey();
  OverlayEntry? _overlayEntry;

  late final CustomHeaderDropdownController _controller;

  @override
  void initState() {
    super.initState();
    _controller = widget.controller;
    _controller._bind(
      show: _showOverlay,
      hide: _removeOverlay,
    );
  }

  void _showOverlay() {
    if (_overlayEntry != null) return;

    final RenderBox renderBox =
        _headerKey.currentContext!.findRenderObject() as RenderBox;
    final Offset offset = renderBox.localToGlobal(Offset.zero);
    final Size size = renderBox.size;

    _overlayEntry = OverlayEntry(
      builder: (context) {
        return Stack(
          children: [
            GestureDetector(
              onTap: _removeOverlay,
              behavior: HitTestBehavior.translucent,
              child: Container(
                width: MediaQuery.of(context).size.width,
                height: MediaQuery.of(context).size.height,
                color: Colors.transparent,
              ),
            ),
            Positioned(
              top: offset.dy + size.height,
              left: 0,
              right: 0,
              bottom: 0,
              child: IgnorePointer(
                child: Container(
                  width: double.infinity,
                  height: double.infinity,
                  color: Colors.black.withOpacity(0.2),
                ),
              ),
            ),
            Positioned(
              top: offset.dy + size.height,
              left: 0,
              right: 0,
              child: Material(
                // 这里为了下拉底部的阴影
                elevation: 2,
                color: widget.dropDownBgColor ?? Colors.transparent,
                child: widget.dropdownBuilder(widget.controller),
              ),
            ),
          ],
        );
      },
    );

    Overlay.of(context).insert(_overlayEntry!);
    _controller._setShown(true);
  }

  void _removeOverlay() {
    if (_overlayEntry != null) {
      _overlayEntry?.remove();
      _overlayEntry = null;
      _controller._setShown(false);
    }
  }

  @override
  void dispose() {
    _removeOverlay();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      key: _headerKey,
      onTap: () {
        widget.onTitleTap(widget.controller);
      },
      child: Container(
        height: widget.headerHeight,
        width: double.infinity,
        color:
            widget.headerBgColor ?? KqThemeManager.getCommonConfig().mainColor,
        alignment: Alignment.center,
        child: widget.header,
      ),
    );
  }
}

class CustomHeaderDropdownController extends ChangeNotifier {
  VoidCallback? _showCallback;
  VoidCallback? _hideCallback;
  bool _isShown = false;

  bool get isShown => _isShown;

  void _bind({
    required VoidCallback show,
    required VoidCallback hide,
  }) {
    _showCallback = show;
    _hideCallback = hide;
  }

  void show() {
    if (_isShown) {
      hide();
    }
    _showCallback?.call();
  }

  void hide() {
    if (_isShown) _hideCallback?.call();
  }

  void _setShown(bool value) {
    if (_isShown != value) {
      _isShown = value;
      notifyListeners();
    }
  }

  @override
  void dispose() {
    _showCallback = null;
    _hideCallback = null;
    super.dispose();
  }
}
